
from dryfire.model.targetModel import DryFireTargetModel, DryFireTargetPartNode
from dryfire.model.shapeModel import OutdoorShapeModel, DryFireShapeModel
from dryfire.model.spaceModel import OutdoorSpaceModel, DryFireSpaceModel

__all__ = ('BeerCanDryFireTargetModel',
           'PaperPlateDryFireTargetModel',
           'HeadDryFireTargetModel',
           'HipsAndHeadDryFireTargetModel',
           'TorsoDryFireTargetModel',
           'ISPCMetricCZoneDryFireTargetModel',
           'ISPCClassicCZoneDryFireTargetModel')

def _centimetersToInches(cents):
    return cents * 0.3937007874015748


class BeerCanDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'Beer Can.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        desc_list = []
        # add the head
        w = 2.5
        h = 5.0
        desc_text = 'The beer can is represented as a rectancle which is'\
            ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model = OutdoorShapeModel(w, w, h,
                                    OutdoorShapeModel.shape_rectangle,
                                    self._outdoor_distance_yards,
                                    desc)
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # rebuild the description
        desc_list.insert(0, self._description)
        self._description = '\n'.join(desc_list)


class PaperPlateDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'Paper Plate.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        desc_list = []
        # add the head
        w = 9.45
        h = 9.45
        desc_text = 'The paper plate is represented as a circle which is'\
                    ' {0} inches wide and {1} inches high.'\
                    '\nAt 100 yards the paper plate is 9 MOA high and wide.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model = OutdoorShapeModel(w, w, h,
                                    OutdoorShapeModel.shape_circle,
                                    self._outdoor_distance_yards,
                                    desc)
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # rebuild the description
        desc_list.insert(0, self._description)
        self._description = '\n'.join(desc_list)


class HeadDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'Head.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        desc_list = []
        # add the head
        w = 6
        h = 6
        desc_text = 'The head is represented as a circle which is'\
            ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model = OutdoorShapeModel(w, w, h,
                                    OutdoorShapeModel.shape_circle,
                                    self._outdoor_distance_yards,
                                    desc)
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # rebuild the description
        desc_list.insert(0, self._description)
        self._description = '\n'.join(desc_list)


class HipsAndHeadDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'Hips and Head.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        desc_list = []
        w = 15
        h = 6 # 8
        desc_text = 'The unprotected hips are represented as a rectangle which is'\
            ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.append(desc)
        o_model1 = OutdoorShapeModel(w, w, h,
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     desc)
        d_model1 = DryFireShapeModel(o_model1, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model1)
        self._parts_list.append(self._parts_tree)
        # add the space
        w = 0
        h = 14
        desc_text = 'The chest area which is {0} inches in height'\
            ' is not a target because it is protected by a plate carrier.'
        desc = desc_text.format(h)
        desc_list.insert(0, desc)
        o_model2 = OutdoorSpaceModel(w, w, h,
                                     self._outdoor_distance_yards,
                                     desc)
        d_model2 = DryFireSpaceModel(o_model2, self._indoor_distance_feet)
        space_part = DryFireTargetPartNode(d_model2)
        self._parts_tree.node_up = space_part
        space_part.node_down = self._parts_tree
        self._parts_list.append(space_part)
        # add the head
        w = 6
        h = 5
        desc_text = 'The exposed part of the face is represented as a square which is'\
            ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model3 = OutdoorShapeModel(w, w, h,
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     desc)
        d_model3 = DryFireShapeModel(o_model3, self._indoor_distance_feet)
        head_part = DryFireTargetPartNode(d_model3)
        space_part.node_up = head_part
        head_part.node_down = space_part
        self._parts_list.append(head_part)
        # rebuild the description
        desc_list.insert(0, self._description)
        self._description = '\n'.join(desc_list)


class TorsoDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'Torso.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        desc_list = []
        w = 15
        h = 22
        desc_text = 'The chest and hips are represented as a single rectangle which is'\
            ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model = OutdoorShapeModel(w, w, h,
                                    OutdoorShapeModel.shape_rectangle,
                                    self._outdoor_distance_yards,
                                    self._description)
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # add the head
        w = 6
        h = 6
        desc_text = 'The head is represented as a square which is'\
                    ' {0} inches wide and {1} inches high.'
        desc = desc_text.format(w, h)
        desc_list.insert(0, desc)
        o_model2 = OutdoorShapeModel(w, w, h,
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     desc)
        d_model2 = DryFireShapeModel(o_model2, self._indoor_distance_feet)
        head_part = DryFireTargetPartNode(d_model2)
        self._parts_tree.node_up = head_part
        head_part.node_down = self._parts_tree
        self._parts_list.append(head_part)
        # rebuild the description
        desc_list.insert(0, self._description)
        self._description = '\n'.join(desc_list)


class ISPCMetricCZoneDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'IPSC Metric C Zone.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        o_model = OutdoorShapeModel(_centimetersToInches(30),
                                    _centimetersToInches(20),
                                    _centimetersToInches(12),
                                    OutdoorShapeModel.shape_quad,
                                    self._outdoor_distance_yards,
                                    "")
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # add the torso
        o_model2 = OutdoorShapeModel(_centimetersToInches(30),
                                     _centimetersToInches(30),
                                     _centimetersToInches(28),
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     "")
        d_model2 = DryFireShapeModel(o_model2, self._indoor_distance_feet)
        torso_part = DryFireTargetPartNode(d_model2)
        self._parts_tree.node_up = torso_part
        torso_part.node_down = self._parts_tree
        self._parts_list.append(torso_part)
        # add the shoulders
        o_model3 = OutdoorShapeModel(_centimetersToInches(15),
                                     _centimetersToInches(30),
                                     _centimetersToInches(5),
                                    OutdoorShapeModel.shape_quad,
                                    self._outdoor_distance_yards,
                                    "")
        d_model3 = DryFireShapeModel(o_model3, self._indoor_distance_feet)
        shoulder_part = DryFireTargetPartNode(d_model3)
        torso_part.node_up = shoulder_part
        shoulder_part.node_down = torso_part
        self._parts_list.append(shoulder_part)
        # add the head
        o_model4 = OutdoorShapeModel(_centimetersToInches(15),
                                     _centimetersToInches(15),
                                     _centimetersToInches(15),
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     "")
        d_model4 = DryFireShapeModel(o_model4, self._indoor_distance_feet)
        head_part = DryFireTargetPartNode(d_model4)
        shoulder_part.node_up = head_part
        head_part.node_down = shoulder_part
        self._parts_list.append(head_part)
        # description
        self._description = "This is the ISPC Metric C Zone target. The torso is 30 centimeters wide and 45 centimeters high. The head is a 15 centimeters square."


class ISPCClassicCZoneDryFireTargetModel(DryFireTargetModel):
    def __init__(self):
        DryFireTargetModel.__init__(self, 'IPSC Classic C Zone.')
        self._build()
        self._set_sizer()

    # private methods

    def _build(self):
        # build from bottom to top
        # add the hips
        o_model = OutdoorShapeModel(_centimetersToInches(30),
                                    _centimetersToInches(10),
                                    _centimetersToInches(10),
                                    OutdoorShapeModel.shape_quad,
                                    self._outdoor_distance_yards,
                                    "")
        d_model = DryFireShapeModel(o_model, self._indoor_distance_feet)
        self._parts_tree = DryFireTargetPartNode(d_model)
        self._parts_list.append(self._parts_tree)
        # add the torso
        o_model2 = OutdoorShapeModel(_centimetersToInches(30),
                                     _centimetersToInches(30),
                                     _centimetersToInches(14.5),
                                     OutdoorShapeModel.shape_rectangle,
                                     self._outdoor_distance_yards,
                                     "")
        d_model2 = DryFireShapeModel(o_model2, self._indoor_distance_feet)
        torso_part = DryFireTargetPartNode(d_model2)
        self._parts_tree.node_up = torso_part
        torso_part.node_down = self._parts_tree
        self._parts_list.append(torso_part)
        # add the shoulders
        o_model3 = OutdoorShapeModel(_centimetersToInches(15),
                                     _centimetersToInches(30),
                                     _centimetersToInches(19),
                                    OutdoorShapeModel.shape_quad,
                                    self._outdoor_distance_yards,
                                    "")
        d_model3 = DryFireShapeModel(o_model3, self._indoor_distance_feet)
        shoulder_part = DryFireTargetPartNode(d_model3)
        torso_part.node_up = shoulder_part
        shoulder_part.node_down = torso_part
        self._parts_list.append(shoulder_part)
        # description
        self._description = "This is the ISPC Classic C Zone target. It is 30 centimeters wide and 45 centimeters high."
